

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:kmxy_base/widget/grid_list_view.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

typedef Cell1WidgetCallback = Widget Function(String? titleData);
typedef TitleWidgetCallback = Widget Function(String? titleData, int index);
typedef Cell1ContentWidgetCallback = Widget Function(
    String? contentData, int index, Map itemData);
typedef ContentWidgetCallback = Widget Function(
    String? contentData, int index, String key, Map itemData);
typedef ItemClickCallback = void Function(Map itemData, int index);
typedef TableListViewCreatedCallback = void Function(
    TableListViewController controller);

class TitleData {
  String data = '';
  double width = 0;
  String contentKey = "";

  TitleData(this.data, this.width, this.contentKey);
}

class TableListView extends StatefulWidget {
  // 标题
  final List<TitleData> titleList;
  // 数据
  final List dataList;
  // 标题的高度
  final double titleHeight;
  // 标题上第一个单元格的宽度
  // 内容的高度
  final double contentHeight;
  // 是否开启下拉加载更多
  final bool enablePullDown;
  // 是否开启上拉刷新
  final bool enablePullUp;
  // 没有数据的view
  final Widget? noDataView;
  // 边框宽度
  final double borderWidth;
  // 边框颜色
  final Color borderColor;
  // 标题背景颜色
  final Color titleBgColor;
  // 内容背景颜色
  final Color contentBgColor;
  // 第一个单元格标题回调
  final Cell1WidgetCallback cell1WidgetCallback;
  // 标题回调
  final TitleWidgetCallback titleWidgetCallback;
  // 第一个单元格内容回调
  final Cell1ContentWidgetCallback cell1ContentWidgetCallback;
  // 内容回调
  final ContentWidgetCallback contentWidgetCallback;
  // 条目点击回调
  final ItemClickCallback? itemClickCallback;
  // 数据更新控制器回调
  final TableListViewCreatedCallback onTableListViewCreated;
  final OnRefresh? onRefresh;
  final OnLoading? onLoading;
  // 是否是竖屏
  final bool isVertical;
  // 宽度差值，横屏是用到
  final double widthGap;
  // 异常 Incorrect use of ParentDataWidget. 选择false
  final bool isExpanded;
  // 边框圆角
  final double borderRadiusTopLeft;
  final double borderRadiusTopRight;
  final double borderRadiusBottomLeft;
  final double borderRadiusBottomRight;
  // 是否显示边框
  final bool isBorder;
  // 是否显示标题和内容的分割线，颜色、高度与边框共用
  final bool isTitleBottomDivider;
  // 是否开启纵向滚滚动
  final bool isVerticalScroll;
  // 是否开启横向滚滚动
  final bool isHorizontalScroll;
  // 横向偏差值
  final double offsetHorizontal;

  const TableListView({
    required this.onTableListViewCreated,
    required this.titleList,
    required this.dataList,
    required this.titleHeight,
    required this.contentHeight,
    required this.cell1WidgetCallback,
    required this.titleWidgetCallback,
    required this.cell1ContentWidgetCallback,
    required this.contentWidgetCallback,
    this.enablePullDown = true,
    this.enablePullUp = true,
    this.noDataView,
    this.borderWidth = 0,
    this.borderColor = Colors.grey,
    this.titleBgColor = Colors.white,
    this.contentBgColor = Colors.white,
    this.onRefresh,
    this.onLoading,
    this.itemClickCallback,
    this.isVertical = true,
    this.widthGap = 0,
    this.isExpanded = true,
    this.borderRadiusTopLeft = 0,
    this.borderRadiusTopRight = 0,
    this.borderRadiusBottomLeft = 0,
    this.borderRadiusBottomRight = 0,
    this.isBorder = true,
    this.isTitleBottomDivider = false,
    this.isVerticalScroll = true,
    this.isHorizontalScroll = true,
    this.offsetHorizontal = 0,
    Key? key,
  }) : super(key: key);

  @override
  _TableListViewState createState() => _TableListViewState();
}

class _TableListViewState extends State<TableListView> {
  ScrollController titleControllerH = ScrollController();
  ScrollController leftController = ScrollController();
  ScrollController contentController = ScrollController();
  ScrollController contentControllerH = ScrollController();

  RefreshController refreshController = RefreshController();

  bool titleIsPan = false;
  bool leftIsPan = false;
  bool contentIsPan = false;
  bool isLoading = false;

  titlePanDown(DragDownDetails? onPanDown) {
    titleIsPan = true;
    leftIsPan = false;
    contentIsPan = false;
  }

  leftPanDown(DragDownDetails? onPanDown) {
    leftIsPan = true;
    titleIsPan = false;
    contentIsPan = false;
  }

  contentPanDown(DragDownDetails? onPanDown) {
    contentIsPan = true;
    titleIsPan = false;
    leftIsPan = false;
  }

  @override
  void initState() {
    super.initState();
    leftController.addListener(() {
      if (leftIsPan) {
        contentController.position.moveTo(leftController.offset);
      }
    });
    titleControllerH.addListener(() {
      if (titleIsPan) {
        contentControllerH.position.moveTo(titleControllerH.offset);
      }
    });

    contentController.addListener(() {
      if (contentIsPan) {
        leftController.position.moveTo(contentController.offset);
      }
    });
    contentControllerH.addListener(() {
      if (contentIsPan) {
        titleControllerH.position.moveTo(contentControllerH.offset);
      }
    });
    WidgetsBinding.instance.addPostFrameCallback((mag) {
      widget.onTableListViewCreated(
          TableListViewController(refreshController, this));
    });
  }

  @override
  void dispose() {
    refreshController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return widget.isExpanded
        ? Expanded(child: contentWidget())
        : contentWidget();
  }

  Widget contentWidget() {
    return Column(
      children: [
        Container(
          decoration: BoxDecoration(
            color: widget.titleBgColor,
            // 圆角设置
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(widget.borderRadiusTopLeft),
              topRight: Radius.circular(widget.borderRadiusTopRight),
            ),
          ),
          height: widget.titleHeight,
          child: Row(
            children: [
              Container(
                width: widget.titleList.isEmpty ? 0 : widget.titleList[0].width,
                alignment: Alignment.center,
                decoration: BoxDecoration(
                  border: widget.isBorder
                      ? Border(
                          left: BorderSide(
                              width: widget.borderWidth,
                              color: widget.borderColor),
                          right: BorderSide(
                              width: widget.borderWidth / 2,
                              color: widget.borderColor),
                          top: BorderSide(
                              width: widget.borderWidth,
                              color: widget.borderColor),
                          bottom: BorderSide(
                              width: widget.borderWidth,
                              color: widget.borderColor),
                        )
                      : null,
                ),
                child: widget.cell1WidgetCallback(widget.titleList.isEmpty
                    ? ''
                    // ignore: unnecessary_type_check
                    : (widget.titleList[0].data is String ||
                            // ignore: unnecessary_null_comparison
                            widget.titleList[0].data == null)
                        ? widget.titleList[0].data
                        : widget.titleList[0].data.toString()),
              ),
              GestureDetector(
                onPanDown: titlePanDown,
                child: SizedBox(
                  width: (MediaQuery.of(context).size.width -
                          widget.offsetHorizontal -
                          widget.widthGap) -
                      (widget.titleList.isEmpty
                          ? 0
                          : widget.titleList[0].width),
                  child: SingleChildScrollView(
                    physics: widget.isHorizontalScroll
                        ? null
                        : const NeverScrollableScrollPhysics(),
                    controller: titleControllerH,
                    scrollDirection: Axis.horizontal,
                    child: Row(
                      children: List.generate(
                        widget.titleList.length - 1,
                        (index) => Container(
                          width: widget.titleList[index + 1].width,
                          height: widget.titleHeight,
                          alignment: Alignment.center,
                          decoration: BoxDecoration(
                            border: widget.isBorder
                                ? Border(
                                    left: BorderSide(
                                        width: widget.borderWidth / 2,
                                        color: widget.borderColor),
                                    right: BorderSide(
                                        width: index ==
                                                (widget.titleList.length - 2)
                                            ? widget.borderWidth
                                            : widget.borderWidth / 2,
                                        color: widget.borderColor),
                                    top: BorderSide(
                                        width: widget.borderWidth,
                                        color: widget.borderColor),
                                    bottom: BorderSide(
                                        width: widget.borderWidth,
                                        color: widget.borderColor),
                                  )
                                : null,
                          ),
                          child: widget.titleWidgetCallback(
                              // ignore: unnecessary_type_check
                              (widget.titleList[index + 1].data is String ||
                                      // ignore: unnecessary_null_comparison
                                      widget.titleList[index + 1].data == null)
                                  ? widget.titleList[index + 1].data
                                  : widget.titleList[index + 1].data.toString(),
                              index + 1),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
        Container(height: widget.borderWidth, color: widget.borderColor),
        Expanded(
          child: SmartRefresher(
            enablePullDown: widget.enablePullDown,
            enablePullUp: widget.enablePullUp,
            header: const WaterDropHeader(
              complete: Text("数据刷新"),
              failed: Text("没有数据了"),
            ),
            footer: CustomFooter(
              builder: (BuildContext context, LoadStatus? mode) {
                Widget body;
                if (mode == LoadStatus.idle) {
                  body = const Text("上拉加载");
                } else if (mode == LoadStatus.loading) {
                  body = const CupertinoActivityIndicator();
                } else if (mode == LoadStatus.failed) {
                  body = const Text("加载失败,点击重试");
                } else if (mode == LoadStatus.canLoading) {
                  body = const Text("松手,加载更多");
                } else {
                  body = const Text("没有更多数据了");
                }
                return SizedBox(
                  height: 55,
                  child: Center(child: body),
                );
              },
            ),
            controller: refreshController,
            onRefresh: widget.onRefresh,
            onLoading: widget.onLoading,
            child: widget.dataList.isEmpty
                ? (widget.noDataView ??
                    Container(
                      alignment: Alignment.center,
                      child: Text(isLoading ? '加载中...' : '没有数据'),
                    ))
                : Container(
                    decoration: BoxDecoration(
                      color: widget.contentBgColor,
                      // 圆角设置
                      borderRadius: BorderRadius.only(
                        bottomLeft:
                            Radius.circular(widget.borderRadiusBottomLeft),
                        bottomRight:
                            Radius.circular(widget.borderRadiusBottomRight),
                      ),
                    ),
                    child: Row(
                      children: [
                        GestureDetector(
                          onPanDown: leftPanDown,
                          child: SingleChildScrollView(
                            physics: widget.isVerticalScroll
                                ? null
                                : const NeverScrollableScrollPhysics(),
                            controller: leftController,
                            child: Column(
                              children: List.generate(
                                widget.dataList.length,
                                (index) => InkWell(
                                  onTap: () {
                                    if (widget.itemClickCallback != null) {
                                      widget.itemClickCallback!(
                                          widget.dataList[index], index);
                                    }
                                  },
                                  child: Container(
                                    width: widget.titleList.isEmpty
                                        ? 0
                                        : widget.titleList[0].width,
                                    height: widget.contentHeight,
                                    alignment: Alignment.center,
                                    decoration: BoxDecoration(
                                      border: widget.isBorder
                                          ? Border(
                                              left: BorderSide(
                                                  width: widget.borderWidth,
                                                  color: widget.borderColor),
                                              right: BorderSide(
                                                  width: widget.borderWidth / 2,
                                                  color: widget.borderColor),
                                              top: BorderSide(
                                                  width: 0,
                                                  color: widget.borderColor),
                                              bottom: BorderSide(
                                                  width: widget.borderWidth,
                                                  color: widget.borderColor),
                                            )
                                          : null,
                                    ),
                                    child: widget.cell1ContentWidgetCallback(
                                        (widget.dataList[index][widget
                                                    .titleList[0]
                                                    .contentKey] is String ||
                                                widget.dataList[index][widget
                                                        .titleList[0]
                                                        .contentKey] ==
                                                    null)
                                            ? widget.dataList[index]
                                                [widget.titleList[0].contentKey]
                                            : widget.dataList[index]
                                                    [widget.titleList[0].contentKey]
                                                .toString(),
                                        index,
                                        widget.dataList[index]),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ),
                        SizedBox(
                          width: (MediaQuery.of(context).size.width -
                                  widget.offsetHorizontal -
                                  widget.widthGap) -
                              (widget.titleList.isEmpty
                                  ? 0
                                  : widget.titleList[0].width),
                          child: GestureDetector(
                            onPanDown: contentPanDown,
                            child: SingleChildScrollView(
                              physics: widget.isVerticalScroll
                                  ? null
                                  : const NeverScrollableScrollPhysics(),
                              controller: contentController,
                              child: SingleChildScrollView(
                                physics: widget.isHorizontalScroll
                                    ? null
                                    : const NeverScrollableScrollPhysics(),
                                controller: contentControllerH,
                                scrollDirection: Axis.horizontal,
                                child: Column(
                                  children: List.generate(
                                    widget.dataList.length,
                                    (index) => InkWell(
                                      onTap: () {
                                        if (widget.itemClickCallback != null) {
                                          widget.itemClickCallback!(
                                              widget.dataList[index], index);
                                        }
                                      },
                                      child: Row(
                                        children: List.generate(
                                          widget.titleList.length - 1,
                                          (indexN) => Container(
                                            width: widget
                                                .titleList[indexN + 1].width,
                                            height: widget.contentHeight,
                                            alignment: Alignment.center,
                                            decoration: BoxDecoration(
                                              border: widget.isBorder
                                                  ? Border(
                                                      left: BorderSide(
                                                          width: widget
                                                              .borderWidth,
                                                          color: widget
                                                              .borderColor),
                                                      right: BorderSide(
                                                          width: index ==
                                                                  (widget.titleList
                                                                          .length -
                                                                      2)
                                                              ? widget
                                                                  .borderWidth
                                                              : widget.borderWidth /
                                                                  2,
                                                          color: widget
                                                              .borderColor),
                                                      top: BorderSide(
                                                          width: 0,
                                                          color: widget
                                                              .borderColor),
                                                      bottom: BorderSide(
                                                          width: widget
                                                              .borderWidth,
                                                          color: widget
                                                              .borderColor),
                                                    )
                                                  : null,
                                            ),
                                            child: widget.contentWidgetCallback(
                                                (widget.dataList[index]
                                                                [widget.titleList[indexN + 1].contentKey]
                                                            is String ||
                                                        widget.dataList[index][widget.titleList[indexN + 1].contentKey] ==
                                                            null)
                                                    ? widget.dataList[index][widget
                                                        .titleList[indexN + 1]
                                                        .contentKey]
                                                    : widget
                                                        .dataList[index][widget
                                                            .titleList[indexN + 1]
                                                            .contentKey]
                                                        .toString(),
                                                indexN,
                                                widget.titleList[indexN + 1].contentKey,
                                                widget.dataList[index]),
                                          ),
                                        ),
                                      ),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
          ),
        ),
      ],
    );
  }

  setIsLoading(bool loadingState) {
    setState(() {
      isLoading = loadingState;
    });
  }
}

class TableListViewController {
  late RefreshController refreshController;
  late _TableListViewState viewState;

  TableListViewController(
      RefreshController controller, _TableListViewState state) {
    refreshController = controller;
    viewState = state;
    viewState.setIsLoading(true);
  }

  /// true 没有更多数据
  void onFinishLoading(bool isNoData) {
    if (isNoData) {
      refreshController.loadNoData();
    } else {
      refreshController.loadComplete();
    }
    viewState.setIsLoading(false);
  }

  onFinishRefresh() {
    refreshController.loadComplete();
    refreshController.refreshCompleted();
    viewState.setIsLoading(false);
  }

  setIsLoading(bool loadingState) {
    viewState.setIsLoading(loadingState);
  }
}
